package com.kun.springsecurity.config;

import com.kun.springsecurity.handler.MyAccessDeniedHandler;
import com.kun.springsecurity.handler.MyAuthenticationFailureHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.util.UrlPathHelper;

/**
 * @Author zhoukun
 * @Date 2021/2/15 17:11
 */
/*
 * Spring Security配置
 */
@Configuration
@EnableWebSecurity
//开启Secured注解
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyAccessDeniedHandler accessDeniedHandler;

    @Autowired
   PersistentTokenRepository persistentTokenRepository;

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    // 向容器中注入PasswordEncoder实例
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 自定义登录页面
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //表单提交
            http.formLogin()// 表单登录方式
                .loginPage("/login")//自定义登录页面
                .loginProcessingUrl("/login/form")  //必须和表单提交的接口路径一致，会去执行自定义登录逻辑
                .successForwardUrl("/toMain")    //登录成功后跳转到的页面，只接受post请求
               .failureForwardUrl("/error") //登陆失败跳转页面
//                 .failureHandler(new MyAuthenticationFailureHandler("/error"))
            ;

            //异常处理（权限不足处理）
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);


        //授权
        http.authorizeRequests()
                .antMatchers("/login").permitAll()//放行的路径
                .antMatchers("/css/**","/js/**","/images/**").permitAll()//放行静态资源
                .regexMatchers(".+[.]png").permitAll()//正则匹配放行
//                .regexMatchers(HttpMethod.POST,"/test/hello").permitAll()//正则匹配规定请求方式
                //用户授权
                //拥有admin1这个权限才能访问main1.html这个页面。
                .antMatchers("/child/child1").hasAnyAuthority("child1")
                //基于IP地址判断，只有这个ip才允许访问
//                .antMatchers("/child/child2").hasIpAddress("127.0.0.1")
                .anyRequest().authenticated();//除了放行路径，其他路径都需要授权;


        //记住我功能
        //记住我功能
        http.rememberMe()
                //参数名，和表单中的一样
                .rememberMeParameter("rememberMe")
                //持久层对象
                .tokenRepository(persistentTokenRepository)
                //登录逻辑设置
                .userDetailsService(userDetailsService)
                //失效时间，默认为两周，这里设为60秒
                .tokenValiditySeconds(60);

        //用户退出
        http.logout()
                .logoutUrl("/logout")//退出的url，默认/logout 打开csrf防护，需要post
                .logoutSuccessUrl("/login")//退出成功返回的url

        ;


//        //关闭csrf防护
        //       http.csrf().disable();


    }
}
